package com.spring.demo8.eg6;

import org.junit.Test;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
import org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.lang.Nullable;
import com.spring.demo8.eg1.Car;

import java.util.*;
import java.lang.reflect.Constructor;
import java.util.stream.Collectors;

/**
 * @author vhans
 */
public class BeanPostProcessorTest {
    /**
     * 使用自定义的实例化bean
     */
    @Test
    public void test1() {
        DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
        // 添加一个BeanPostProcessor: InstantiationAwareBeanPostProcessor
        factory.addBeanPostProcessor(new InstantiationAwareBeanPostProcessor() {
            @Override
            @Nullable
            public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
                System.out.println("调用postProcessBeforeInstantiation()");
                // 发现类型是Car时，硬编码创建一个Car对象返回
                if (beanClass == Car.class) {
                    Car car = new Car();
                    car.setName("保时捷");
                    return car;
                }
                return null;
            }
        });
        // 定义一个宝马
        AbstractBeanDefinition carBeanDefinition = BeanDefinitionBuilder.genericBeanDefinition(Car.class)
                .addPropertyValue("name", "宝马")
                .getBeanDefinition();
        factory.registerBeanDefinition("car", carBeanDefinition);
        // 可以发现结果为保时捷
        System.out.println(factory.getBean("car"));
    }

    /**
     * 使用自定义的构造器进行实例化
     */
    @Test
    public void test2() {
        DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
        // 添加一个BeanPostProcessor: SmartInstantiationAwareBeanPostProcessor
        factory.addBeanPostProcessor(new SmartInstantiationAwareBeanPostProcessor() {
            @Override
            @Nullable
            public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) throws BeansException {
                System.out.println("调用determineCandidateConstructors()");
                // 获取所有构造器
                Constructor<?>[] declaredConstructors = beanClass.getDeclaredConstructors();
                if (declaredConstructors.length != 0) {
                    // 获取有@MyAutowired注解标注的构造器
                    Constructor<?>[] constructors = Arrays.stream(declaredConstructors)
                            .filter(constructor -> constructor.isAnnotationPresent(MyAutowired.class)).toArray(Constructor[]::new);
                    return constructors.length != 0 ? constructors : null;
                } else {
                    return null;
                }
            }
        });

        factory.registerBeanDefinition("name",
                BeanDefinitionBuilder.genericBeanDefinition(String.class)
                        .addConstructorArgValue("Vhans")
                        .getBeanDefinition());

        factory.registerBeanDefinition("age",
                BeanDefinitionBuilder.genericBeanDefinition(Integer.class)
                        .addConstructorArgValue(20)
                        .getBeanDefinition());

        factory.registerBeanDefinition("person",
                BeanDefinitionBuilder.genericBeanDefinition(Person.class)
                        .getBeanDefinition());

        Person person = factory.getBean("person", Person.class);
        System.out.println(person);
    }
}
